package upload

import (
	"errors"
	"fmt"

	"img_analyse/utils"
	"time"

	"io"
	"mime/multipart"
	"os"
	"path/filepath"

	"strings"
)

// WhiteImageList 定义支持的图片文件类型
var WhiteImageList = map[string]struct{}{
	".jpg":  {},
	".png":  {},
	".jpeg": {},
	".ico":  {},
	".tiff": {},
	".gif":  {},
	".svg":  {},
	".webp": {},
}

// OSS 接口定义
type OSS interface {
	UploadImage(file *multipart.FileHeader) (string, string, error)
	DeleteImage(key string) error
}

// System 系统配置
type System struct {
	Host           string `json:"-" yaml:"host"`                          // 服务器绑定的主机地址，通常为 0.0.0.0 表示监听所有可用地址
	Port           int    `json:"-" yaml:"port"`                          // 服务器监听的端口号，通常用于 HTTP 服务
	Env            string `json:"-" yaml:"env"`                           // Gin 的环境类型，例如 "debug"、"release" 或 "test"
	RouterPrefix   string `json:"-" yaml:"router_prefix"`                 // API 路由前缀，用于构建 API 路径
	UseMultipoint  bool   `json:"use_multipoint" yaml:"use_multipoint"`   // 是否启用多点登录拦截，防止同一账户在多个地方同时登录
	SessionsSecret string `json:"sessions_secret" yaml:"sessions_secret"` // 用于加密会话的密钥，确保会话数据的安全性
	OssType        string `json:"oss_type" yaml:"oss_type"`               // 对应的对象存储服务类型，如 "local" 或 "qiniu"
}
type Upload struct {
	Size int    `json:"size" yaml:"size"` // 图片上传的大小，单位 MB
	Path string `json:"path" yaml:"path"` // 图片上传的目录
}

func (s System) Addr() string {
	return fmt.Sprintf("%s:%d", s.Host, s.Port)
}

type Config struct {
	System System `json:"system" yaml:"system"`
	Upload Upload `json:"upload" yaml:"upload"`
}

var config *Config

// NewOss 根据配置返回相应存储类型的 OSS 实例
func NewOss() OSS {
	switch config.System.OssType {
	case "local":
		return &Local{}

	default:
		return &Local{}
	}
}

type Local struct {
}

func (*Local) UploadImage(file *multipart.FileHeader) (string, string, error) {
	size := float64(file.Size) / float64(1024*1024)
	if size >= float64(config.Upload.Size) {
		return "", "", fmt.Errorf("the image size exceeds the set size, the current size is: %.2f MB, the set size is: %d MB", size, config.Upload.Size)

	}

	ext := filepath.Ext(file.Filename)
	name := strings.TrimSuffix(file.Filename, ext)
	if _, exists := WhiteImageList[ext]; !exists {
		return "", "", errors.New("don't upload files that aren't image types")
	}

	filename := utils.MD5V([]byte(name)) + "-" + time.Now().Format("20060102150405") + ext
	path := config.Upload.Path + "/image/"

	if err := os.MkdirAll(path, os.ModePerm); err != nil {
		return "", "", err
	}

	Filepath := path + filename

	out, err := os.Create(Filepath)
	if err != nil {
		return "", "", err
	}
	defer func(out *os.File) {
		_ = out.Close()
	}(out)

	f, err := file.Open()
	if err != nil {
		return "", "", err
	}
	defer func(f multipart.File) {
		_ = f.Close()
	}(f)

	if _, err = io.Copy(out, f); err != nil {
		return "", "", err
	}

	return "/" + Filepath, filename, nil
}

func (*Local) DeleteImage(key string) error {
	path := config.Upload.Path + "/image/" + key
	return os.Remove(path)
}
